package com.icesoft.core.dao.base;

import com.icesoft.core.dao.criteria.FromBuilder;
import com.icesoft.core.dao.criteria.Page;
import com.icesoft.core.dao.criteria.QueryBuilder;
import com.icesoft.core.dao.criteria.SelectBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;

import javax.persistence.Query;
import java.util.Collection;
import java.util.List;

/**
 * @author XHH
 */
public abstract class BaseDao<T extends Model> extends RawType<T> {
    @Autowired
    private DaoFacade dao;

    /**
     * 创建
     *
     * @param model 数据库实体
     */
    public void create(T model) {
        if (model.getId() != null) {
            if (model.getId() == 0) {
                model.setId(null);
            } else {
                throw new IllegalArgumentException("新建数据id必须为null");
            }
        }
        dao.create(model);
    }

    /**
     * 更新
     *
     * @param model 数据库实体
     */
    public void update(T model) {
        dao.update(model);
    }

    /**
     * 批量创建
     *
     * @param models 数据库实体集合
     */
    public void create(Collection<T> models) {
        if (models.isEmpty()) {
            return;
        }
        dao.batchCreate(models);
    }

    /**
     * 批量更新
     *
     * @param models 数据库实体集合
     */
    public void update(Collection<T> models) {
        if (models.isEmpty()) {
            return;
        }
        dao.batchUpdate(models);
    }

    /**
     * 删除
     *
     * @param model 数据库实体
     */
    public void delete(T model) {
        dao.delete(model);
    }

    /**
     * 删除 {@link #delete(FromBuilder)}
     *
     * @param queryBuilder 查询条件
     */
    protected void delete(QueryBuilder queryBuilder) {
        delete(queryBuilder.from(getRawClass()));
    }

    protected void delete(FromBuilder fromBuilder) {
        fromBuilder.setFromTable(getRawClass());
        List<T> list = find(fromBuilder);
        delete(list);
    }

    /**
     * 删除
     *
     * @param models 数据库实体
     */
    public void delete(Collection<T> models) {
        if (models.isEmpty()) {
            return;
        }
        dao.batchDelete(models);
    }

    /**
     * 分页查询，不分页请使用list方法 {@link #page(FromBuilder)}
     *
     * @param queryBuilder 查询条件
     */
    protected Page<T> page(QueryBuilder queryBuilder) {
        return page(queryBuilder.from(getRawClass()));
    }

    protected Page<T> page(FromBuilder fromBuilder) {
        if (isDefaultIdDesc() && fromBuilder.order().isEmpty()) {
            fromBuilder.order().desc("id");
        }
        return pageSelect(SelectBuilder.selectFrom(fromBuilder));
    }

    protected <D> Page<D> pageSelect(SelectBuilder selectBuilder) {
        FromBuilder fromBuilder = selectBuilder.getFromBuilder();
        fromBuilder.setFromTable(getRawClass());
        Page<D> page = new Page<>();
        int count = count(fromBuilder);
        page.setTotal(count);
        if (count == 0) {
            return page;
        }
        List<D> list = findSelect(selectBuilder);
        page.setData(list);
        return page;
    }

    /**
     * 查询 {@link #find(FromBuilder)}
     *
     */
    @NonNull
    protected List<T> find(QueryBuilder queryBuilder) {
        return find(queryBuilder.from(getRawClass()));
    }

    protected List<T> find(FromBuilder fromBuilder) {
        return findSelect(SelectBuilder.selectFrom(fromBuilder));
    }

    protected <D> List<D> findSelect(SelectBuilder selectBuilder) {
        FromBuilder fromBuilder = selectBuilder.getFromBuilder();
        fromBuilder.setFromTable(getRawClass());
        return dao.findList(selectBuilder);
    }

    protected boolean isDefaultIdDesc() {
        return true;
    }

    protected T unique(FromBuilder fromBuilder) {
        return uniqueSelect(SelectBuilder.selectFrom(fromBuilder));
    }

    protected <D> D uniqueSelect(SelectBuilder selectBuilder) {
        FromBuilder fromBuilder = selectBuilder.getFromBuilder();
        fromBuilder.setFromTable(getRawClass());
        return dao.findSingle(selectBuilder);
    }

    /**
     * 查询数量
     *
     * @param fromBuilder 查询条件
     * {@link FromBuilder#get()}
     * @return 满足条件的数量
     */
    protected int count(FromBuilder fromBuilder) {
        fromBuilder.setFromTable(getRawClass());
        return dao.count(fromBuilder);
    }

    /**
     * 是否存在
     *{@link FromBuilder#get()}
     * @return 是否存在
     */
    protected boolean isExist(FromBuilder fromBuilder) {
        fromBuilder.setFromTable(getRawClass());
        return dao.isExist(fromBuilder);
    }

    /**
     * 查询已存在的单个记录 {@link #unique(FromBuilder)}
     *
     * @return model or null
     */

    protected T unique(QueryBuilder queryBuilder) {
        return unique(queryBuilder.from(getRawClass()));
    }

    /**
     * load by id
     *
     * @return model or null
     */
    public T load(Integer id) {
        if (id == null || id <= 0) {
            return null;
        }
        return dao.load(getRawClass(), id);
    }

    /**
     * 所有数据
     *
     * @return 所有数据
     */
    public List<T> findAll() {
        return dao.findAll(getRawClass());
    }

    /**
     * 查询数量 {@link #count(FromBuilder)}
     *
     * @return 满足条件的数量
     */
    protected int count(QueryBuilder queryBuilder) {
        return count(queryBuilder.from(getRawClass()));
    }

    /**
     * 所有数量
     *
     * @return 所有数量
     */
    public int countAll() {
        return dao.countAll(getRawClass());
    }

    /**
     * 是否存在 {@link #isExist(FromBuilder)}
     *
     * @return 是否存在
     */
    protected boolean isExist(QueryBuilder queryBuilder) {
        return isExist(queryBuilder.from(getRawClass()));
    }

    protected Query createQuery(String hql) {
        return dao.createQuery(hql);
    }

}
